//*************************************************************************//
//*           _____   ____________            ______               __     *//
//*          / /__ \ / ____/ ____/           / ____/___  _________/ /     *//
//*     __  / /__/ // __/ / __/    ______   / /_  / __ \/ ___/ __  /      *//
//*    / /_/ // __// /___/ /___   /_____/  / __/ / /_/ / /  / /_/ /       *//
//*    \____//____/_____/_____/           /_/    \____/_/   \__,_/        *//
//*                                                                       *//
//*     Copyright (c) 2006 Ford Argentina. All Rights Reserved.           *//
//*                                                                       *//
//*************************************************************************//

package ar.com.ford.it.webengine.security.jstl.tag;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import org.apache.commons.beanutils.PropertyUtils;
import ar.com.ford.it.webengine.security.helper.SecurityHelper;
import ar.com.ford.it.webengine.wslx.WslxUser;
import com.ford.it.logging.ILogger;
import com.ford.it.logging.Level;
import com.ford.it.logging.LogFactory;

public class TagUtils {
    private static final String CLASS_NAME = TagUtils.class.getName();
    private static final ILogger log = LogFactory.getInstance().getLogger(CLASS_NAME);	
	
	
	private static final TagUtils instance = new TagUtils();
	private static final Map scopes = new HashMap();
	
    static {
        scopes.put("page", new Integer(PageContext.PAGE_SCOPE));
        scopes.put("request", new Integer(PageContext.REQUEST_SCOPE));
        scopes.put("session", new Integer(PageContext.SESSION_SCOPE));
        scopes.put("application", new Integer(PageContext.APPLICATION_SCOPE));
    }

    
    protected TagUtils() {
        super();
    }

    public static TagUtils getInstance() {
        return instance;
    }	

    
    
    public int getScope(String scopeName) throws JspException {
        Integer scope = (Integer) scopes.get(scopeName.toLowerCase());

        if (scope == null) {
            throw new JspException("Invalid bean scope: "+scope);
        }

        return scope.intValue();
    }
	
	public Object lookup(PageContext pageContext, String name, String scopeName) throws JspException {

		if (scopeName == null) {
		    return pageContext.findAttribute(name);
		}
		
		return pageContext.getAttribute(name, instance.getScope(scopeName));
    }
    
	
	public Object lookup(PageContext pageContext, String name, String property, String scope) throws JspException {

		// Look up the requested bean, and return if requested
		Object bean = lookup(pageContext, name, scope);
        if (bean == null) {
            JspException e = null;
            if (scope == null) {
                e = new JspException("Cannot find bean: "+name+" in any scope");
            } 
            else {
                e = new JspException("Cannot find bean: "+name+" in scope: "+scope);
            }
            throw e;
        }

        if (property == null) {
            return bean;
        }

        // Locate and return the specified property
        try {
            Object valor = PropertyUtils.getProperty(bean, property); 
            if (valor != null)
            	return valor.toString();
            
            return null;

        } catch (IllegalAccessException e) {
        	throw new JspException("Invalid access looking up property: "+property+" of bean: "+name);

        } catch (IllegalArgumentException e) {
            throw new JspException("Invalid argument looking up property: "+property+" of bean: "+name);

        } catch (InvocationTargetException e) {
            Throwable t = e.getTargetException();
            if (t == null) {
                t = e;
            }
            throw new JspException("Exception thrown by getter for property: "+property+" of bean: "+name);

        } catch (NoSuchMethodException e) {
            throw new JspException("No getter method for property: "+property+" of bean: "+name);
        } catch (Exception e) {
            throw new JspException(e);
        }
        

    }


    public boolean isAuthorized(PageContext pageContext, String authorizedFor, String relation) throws JspException {
    	String METHOD_NAME = "isAuthorized";
    	
    	SecurityHelper securityHelper = null; 
		if (relation == null || "and".equalsIgnoreCase(relation))
			securityHelper = new SecurityHelper(true);
		else {
			if ("or".equalsIgnoreCase(relation)) {
				securityHelper = new SecurityHelper();
			}
			else {
				JspException e = new JspException("FordArgHandlerTag.authorizedFor - relation solo puede ser AND o OR");
				log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "JspException", e);
				throw e;
			}
		}

		WslxUser user = (WslxUser)this.lookup(pageContext, "wslxuser", null); 
        if (user == null) {
        	JspException e = new JspException("FordArgHandlerTag.authorizedFor");
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "JspException", e);
            throw e;
        }
		
        if (securityHelper.check(user.getPermissions(), authorizedFor)) {
        	return true;
        }
    	
        return false;
    }

   
}
